﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml;
using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace for7raid.vkConnector
{
    public class Request
    {
        public string Name { get; private set; }
        public Dictionary<string, object> Params { get; set; }

        public Request(string Name)
        {
            this.Name = Name;
            Params = new Dictionary<string, object>();
            Params.Add("access_token", vkConnector.Token);
        }

        public Request AddParam(string Name, object value)
        {
            this.Params.Add(Name, value);
            return this;
        }

        public XmlDocument Exec()
        {
            var uri = MakeUri();


          
            var doc = new XmlDocument();
            doc.Load(uri);


            
                    //var item = doc.SelectSingleNode("error");
                    //if (item != null) //произошла неведанная х... ошибка
                    //{
                    //    if (item["error_code"].InnerText == "5") //истек срок действия ключа - авторизуемся повторно
                    //    {
                    //        vkConnector.Login();
                            
                    //        //Application.Current.Dispatcher.Invoke(
                    //        //    (Action)delegate() { vkConnector.Login(); });

                    //        System.Windows.Threading.Dispatcher.FromThread(Application.Current.Dispatcher.Thread).Invoke((Action)delegate() { vkConnector.Login(); });
                    //        Params["access_token"] = vkConnector.Token;
                    //        return Exec();
                    //    }
                    //    else if (item["error_code"].InnerText == "6") //слишком много запросов в секнду. подождем секунду и продолжим
                    //    {
                    //        Thread.Sleep(1000);
                    //        return Exec();
                    //    }
                    //    else
                    //        throw new Exception(item["error_msg"].InnerText);

                    //}
            return doc;
        }

        public string ExecAsString()
        {
            return Exec().ToString();
        }

        public void ExecAsync(Action<XmlDocument> action)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (object sender, DoWorkEventArgs e) =>
                {
                    e.Result = (e.Argument as Request).Exec();
                };
            worker.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) =>
                {
                    if (e.Error != null)
                        throw e.Error;

                    var doc = e.Result as XmlDocument;
                    var item = doc.SelectSingleNode("error");
                    if (item != null) //произошла неведанная х... ошибка
                    {
                        if (item["error_code"].InnerText == "5") //истек срок действия ключа - авторизуемся повторно
                        {
                            vkConnector.Login();
                            Params["access_token"] = vkConnector.Token;
                            ExecAsync(action);
                            return;
                        }
                        else if (item["error_code"].InnerText == "6") //слишком много запросов в секнду. подождем секунду и продолжим
                        {
                            Thread.Sleep(1000);
                            ExecAsync(action);
                            return;
                        }
                        else
                            throw new Exception(item["error_msg"].InnerText);
                    }

                    if(action != null)
                        action(e.Result as XmlDocument);
                };
            worker.RunWorkerAsync(this);
        }

        private string MakeUri()
        {
            return vkConnector.RequestServer + Name + ".xml?" +
                Params.Select(p => p.Key + "=" + p.Value.ToString()).Aggregate((i, k) => k + "&" + i);
        }
    }
}
